#ifndef _FW5_H_
#define _FW5_H_

#ifdef __KERNEL__
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/device.h>
#include <linux/fs.h>
#include <linux/netfilter_ipv4.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <linux/udp.h>
#else  // __KERNEL__
#include <linux/types.h>
#endif // __KERNEL__


// the 3 protocols we will work with
typedef enum {
	PROT_ICMP	= 1,
	PROT_TCP	= 6,
	PROT_UDP	= 17,
	PROT_RES	= 255,
} prot_t;


// 127.0.0.1 in little endian
#define LOCAL_ADDR 0x0100007f



// various reasons to be registered in each log entry
typedef enum {
	REASON_FW_INACTIVE           = -1,
	REASON_NOT_IPV4              = -2,
	REASON_PROT_NOT_ENFORCED     = -3,
	REASON_NO_MATCHING_RULE      = -4,
	REASON_OUT_OF_STATE          = -5,
	REASON_CONNECTION_TABLE_FULL = -6,
	REASON_XMAS_PACKET           = -7,
	REASON_REMOTE_FILE_ATTACK    = -8,
} reason_t;
	

// auxiliary strings, for your convenience
#define DEVICE_NAME_RULES      "rules"
#define DEVICE_NAME_LOG        "log"
#define DEVICE_NAME_CONN_TAB   "conn_tab"
#define CLASS_NAME             "fw5"


// device minor numbers, for your convenience
typedef enum {
	MINOR_RULES    = 0,
	MINOR_LOG      = 1,
	MINOR_CONN_TAB = 2,
} minor_t;


// configuration bits
typedef enum {
	FW_CONFIG_ACTIVE                = 0x01,
	FW_CONFIG_ICMP                  = 0x02,
	FW_CONFIG_TCP                   = 0x04,
	FW_CONFIG_UDP                   = 0x08,
	FW_CONFIG_CONN_TRACK            = 0x10,
	FW_CONFIG_CLEANUP_ACCEPT        = 0x20,
	FW_CONFIG_REMOTE_FILE_PROTECT   = 0x40,
} config_t;


#define RULE_NAME_LENGTH     0x20
#define SEARCH_STRING_LENGTH 0x400
// rule base
typedef struct {
	__u8	protocol; // values from: prot_t
	__u8	src_mask; // valid values: 0-32 
	__u8	dst_mask; // valid values: 0-32
	__u8	action;   // valid values: NF_ACCEPT, NF_DROP
	__be16	src_port; 
	__be16	dst_port;
	__be32	src_ip;
	__be32	dst_ip;
	char    rule_name[RULE_NAME_LENGTH];
	__be32  search_str_len;
	char    search_string[SEARCH_STRING_LENGTH];
} rule_t;


// auxiliary struct for your convenience.
typedef struct {
	__u8 action;  // valid values: NF_ACCEPT, NF_DROP
	int  reason;  // values from: reason_t
} decision_t;


// logging
typedef struct {
	unsigned long  modified;     // seconds since epoch
	unsigned char  protocol;     // values from: prot_t
	unsigned char  action;       // valid values: NF_ACCEPT, NF_DROP
	unsigned char  hooknum;      // as received from netfilter hook
	unsigned char  offset;       // search string match offset
	unsigned int   src_ip;
	unsigned int   dst_ip;
	unsigned short src_port;
	unsigned short dst_port;
	signed int     reason;       // rule#, or values from: reason_t
	unsigned int   count;        // counts this line's hits
} log_row_t;


// connection tracking
typedef struct {
	unsigned int   cli_ip;      // ip of the side that sent the 1st SYN
	unsigned int   ser_ip;      // ip of the other side
	unsigned short cli_port;    // source port of 1st SYN packet
	unsigned short ser_port;    // destination port of 1st SYN packet
	unsigned int   expires;     // in seconds from epoch
	unsigned char  state;       // values from: tcp_conn_t
} connection_t;


// the four states of a TCP connection (simplified!)
typedef enum {
	// connection states
	TCP_CONN_SYN_SENT  = 1,
	TCP_CONN_SYN_ACK   = 2,
	TCP_CONN_ESTAB     = 3,
	TCP_CONN_CLOSING   = 4,
} tcp_conn_t;


// these values represent the number of entries in each mmap()able device,
// they do not represent the size in bytes!
#define RULE_BASE_ENTRIES         0x40
#define LOG_ENTRIES               0x400
#define CONNECTION_TABLE_ENTRIES  0x400
	

#endif // _FW5_H_
